package com.efe.ms.esservice.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.efe.ms.common.vo.PaginationVO;
import com.github.pagehelper.PageInfo;

@Service
public class BaseSearchServiceImpl implements BaseSearchService {

	@Resource
	private ElasticsearchRestTemplate elasticsearchRestTemplate;

	@Resource
	private RestHighLevelClient restHighLevelClient;

	@Override
	public void create(Class<?> t) {
		elasticsearchRestTemplate.indexOps(t);

	}

	@Override
	public List<?> getAllIndex(String keyword, String keyName, String[] fieldsName, String[] excludes,
			int  pageIndex,int pageSize,
			String... indices) {
		List<Object> rest = new ArrayList<>();
		try {
			// 查询条件
			QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(keyName, keyword);

			// 查询创建
			SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
			// 查询语句创建
			searchSourceBuilder.query(matchQueryBuilder);
			// 设置分页 查询条数
			searchSourceBuilder.from(pageIndex);
			searchSourceBuilder.size(pageSize);
			// 查询返回结果字段 _source对象下的字段--- 第一个是需要字段 第二个过滤字段
			searchSourceBuilder.fetchSource(fieldsName, excludes);

			SearchRequest searchRequest = new SearchRequest();
			// 设置索引
			searchRequest.indices(indices);
			// 设置传送的json
			searchRequest.source(searchSourceBuilder);
			// 发送请求
			System.out.println("getAllIndex:"+searchRequest.toString());
			SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
			// 输出打印
			for (SearchHit hit : search.getHits()) {
				Map<String, Object> sourceAsMap = hit.getSourceAsMap();
				rest.add(sourceAsMap);
				System.out.println(hit.toString());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return rest;
	}

	@Override
	public String queryById(String indices, String id) throws IOException {
		GetRequest getRequest = new GetRequest(indices, id);
		GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
		String jsonStr = getResponse.getSourceAsString();
		return jsonStr;
	}

	/**
	 * 查询封装返回json字符串
	 * 
	 * @param indices 引擎库名称可以多个
	 * @param searchSourceBuilder  
	 * @return
	 * @throws IOException
	 */
	@Override
	public String searchToJson(String indices, SearchSourceBuilder searchSourceBuilder) throws IOException {
		//设置引擎库
		SearchRequest searchRequest = new SearchRequest(indices);
		//查询条件
		searchRequest.source(searchSourceBuilder);
		//设置scroll间隔
		searchRequest.scroll(TimeValue.timeValueMinutes(3L));
		SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
		String scrollId = searchResponse.getScrollId();
		System.out.println("scrollId:" + scrollId);
		//检索第一批搜索命中
		SearchHits hits = searchResponse.getHits();
		JSONArray jsonArray = new JSONArray();
		for (SearchHit hit : hits) {
			String sourceAsString = hit.getSourceAsString();
			JSONObject jsonObject = JSON.parseObject(sourceAsString);
			jsonArray.add(jsonObject);
		}
		System.out.println("返回总数为：" + hits.getTotalHits());
		return jsonArray.toJSONString();
	}

	/**
	 * 拼接综合查询 查询条件
	 * 
	 * @param comprehensiveQueryEventVO
	 * @return
	 */
	@Override
	public SearchSourceBuilder getSearchSourceBuilder(Map<String, String> parm,String keyValue, int pageIndex, int pageSize,
			 String orderBy, SortOrder order) {
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		// 分页设置
		sourceBuilder.from(pageIndex);
		sourceBuilder.size(pageSize);
		// track_total_hits=true 显示文件总行数
		sourceBuilder.trackTotalHits(true);
		// 符合条件查询
		BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
		boolBuilder.mustNot(QueryBuilders.termQuery("eventStateId", 0));
		boolBuilder.mustNot(QueryBuilders.termQuery("eventStateId", 11));
		boolBuilder.mustNot(QueryBuilders.termQuery("delateFlag", 1));
		
		// 动态条件----keyword
		if(null != keyValue  && !"".equals(keyValue) ) {
			boolBuilder.must(QueryBuilders.queryStringQuery(keyValue));
		}
		// 拼接动态查询条件
		if (null != parm && parm.size() > 0) {
			for (String key : parm.keySet()) {
				boolBuilder.must(QueryBuilders.termQuery(key, parm.get(key)));
			}
		}
		sourceBuilder.query(boolBuilder);

		// 排序
		FieldSortBuilder fieldSortBuilder = new FieldSortBuilder(orderBy);
		fieldSortBuilder = fieldSortBuilder.order(order);
		sourceBuilder.sort(fieldSortBuilder);

		return sourceBuilder;
	}

	/**
	 * 通用查询分页
	 * 
	 * @param searchSourceBuilder
	 * @param pageNum             页码
	 * @param pageSize            页面数量
	 * @param                     documentClass《T》 映射实体
	 * @return PaginationVO《T》
	 * @throws IOException
	 */
	@Override
	public <T> PaginationVO<T> searchGetPage(SearchSourceBuilder searchSourceBuilder, int pageIndex, int pageSize,
			Class<T> documentClass) throws Exception {
		Document declaredAnnotation = (Document) documentClass.getDeclaredAnnotation(Document.class);
		if (declaredAnnotation == null) {
			throw new Exception(String.format("请检查该documentClass参数类是否使用了@Document注解设置搜索引擎id", documentClass.getName()));
		}
		//索引名称
		String indexName = declaredAnnotation.indexName();
		SearchRequest searchRequest = new SearchRequest(indexName);
		searchRequest.source(searchSourceBuilder);
		//执行数据获取
		SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
		SearchHits hits = searchResponse.getHits();
		JSONArray jsonArray = new JSONArray();
		for (SearchHit hit : hits) {
			//获取es返回中的实体映射数据
			String sourceString = hit.getSourceAsString();
			JSONObject jsonObject = JSON.parseObject(sourceString);
			jsonArray.add(jsonObject);
		}
		System.out.println("返回总数为：" + hits.getTotalHits());
		int total = (int) hits.getTotalHits().value;

		return getPageData(pageIndex, pageSize, documentClass, jsonArray.toJavaList(documentClass), total);
	}

	/***
	 * 封装分页
	 * 
	 * @param pageIndex     第几页
	 * @param pageSize      每页的数量
	 * @param documentClass 映射实体
	 * @param jsonArray     json
	 * @param total         总数为
	 * @return PaginationVO《T》
	 */
	@Override
	public <T> PaginationVO<T> getPageData(int pageIndex, int pageSize, Class<T> documentClass, List<T> list,
			int total) {
		PaginationVO<T> page = new PaginationVO<T>();
		page.setData(list);
		page.setPage(pageIndex);
		page.setPageSize(pageSize);
		page.setTotal(total);
		return page;
	}

}
